/*
* Entourage
* Copyright 2011 INF532@Galatasaray University & Vincent Labatut 
* 
* This file is part of Entourage.
* 
* Entourage is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* 
* Entourage is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with Entourage. If not, see <http://www.gnu.org/licenses/>.
* 
*/

package com.appspot.entourage.graphtools;

import java.util.*;
import org.jdom.*;
import org.jdom.output.*;


/**
 * This class is used to convert relations from
 * the database into GraphML supported format
 * @author Berk PELENK <bpelenk@beengames.com>
 * @version 1
 * @see GraphNode
 * @see GraphEdge
 *
 */
public class GraphMLConverter {
    
    /**
     * method which creates the graphML structure of the list of nodes and edges
     * @param nodes the list of nodes which are represented by persons
     * @param edges list of edges which are represented by relations between persons
     * @return content of the graph as string
	 * @author Berk PELENK <bpelenk@beengames.com>
	 * @version 1
	 * @see GraphNode
	 * @see GraphEdge
     */
    public static String createGraph(List<GraphNode> nodes, List<GraphEdge> edges) {
        // graphml document header
        Element graphml = new Element("graphml","http://graphml.graphdrawing.org/xmlns");
        Document document = new Document(graphml);        
        Namespace xsi = Namespace.getNamespace("xsi","http://www.w3.org/2001/XMLSchema-instance");

        graphml.addNamespaceDeclaration(xsi);
        graphml.setAttribute("schemaLocation", "http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd", xsi);

        Namespace defaultns = Namespace.getNamespace("http://graphml.graphdrawing.org/xmlns");
        
        Element key_d0 = new Element("key");
        key_d0.setNamespace(defaultns);
        key_d0.setAttribute("id","d0");
        key_d0.setAttribute("for","node");
        key_d0.setAttribute("attr.name","person");
        key_d0.setAttribute("attr.type","string");
        graphml.addContent(key_d0);
        
        Element key_d1 = new Element("key");
        key_d1.setNamespace(defaultns);
        key_d1.setAttribute("id","d1");
        key_d1.setAttribute("for","node");
        key_d1.setAttribute("attr.name","guid");
        key_d1.setAttribute("attr.type","string");
        graphml.addContent(key_d1);
        
        Element key_d2 = new Element("key");
        key_d2.setNamespace(defaultns);
        key_d2.setAttribute("id","d2");
        key_d2.setAttribute("for","edge");
        key_d2.setAttribute("attr.name","connections");
        key_d2.setAttribute("attr.type","int");
        graphml.addContent(key_d2);        
        
        Element graph = new Element("graph");
        graph.setNamespace(defaultns);
        graph.setAttribute("id","G");
        graph.setAttribute("edgedefault","undirected");
        
        for (GraphNode node : nodes) {
        	addNode(node.getGuid(), node.getFullName(), graph, defaultns);
        }
        
        int edgeid = 0;
        for (GraphEdge edge : edges) {
        	addEdge(edgeid, edge.getNode1().getGuid(), edge.getNode2().getGuid(), edge.getConnections(), graph, defaultns);
        	edgeid++;
        }
        
        graphml.addContent(graph);
    	XMLOutputter outputter = new XMLOutputter();
        return outputter.outputString(graph);       
    }
    
    /**
     * add a edge to the graphML document
     * @param id the id of the edge
     * @param guidSource the id of the node source
     * @param guidTarget the id of the node target
     * @param connections number of connections between nodes
     * @param graph the graph element of the graphML document
     * @param namespace default namespace to use
	 * @author Berk PELENK <bpelenk@beengames.com>
	 * @version 1
	 * @see GraphNode
	 * @see GraphEdge
     */
    public static void addEdge(int id, String guidSource, String guidTarget, int connections, Element graph, Namespace namespace){
        Element edge = new Element("edge");
        edge.setNamespace(namespace);
        edge.setAttribute("id","e"+id);
        edge.setAttribute("source","n"+guidSource);
        edge.setAttribute("target","n"+guidTarget);
        Element data0 = new Element("data");
        data0.setNamespace(namespace);
        data0.setAttribute("key","d2");
        data0.setText(Integer.toString(connections));
        edge.addContent(data0); 
        graph.addContent(edge);
    }
    
    /**
     * add a node to the graphML document
     * @param guid the id of the node
     * @param name the name data of the node
     * @param graph the graph element of the graphML document
     * @param namespace default namespace to use
	 * @author Berk PELENK <bpelenk@beengames.com>
	 * @version 1
	 * @see GraphNode
	 * @see GraphEdge
     */
    public static void addNode(String guid, String name, Element graph, Namespace namespace){
        Element node = new Element("node");
        node.setNamespace(namespace);
        node.setAttribute("id","n"+guid);
        Element data0 = new Element("data");
        data0.setNamespace(namespace);
        data0.setAttribute("key","d0");
        data0.setText(name);
        node.addContent(data0);
        Element data1 = new Element("data");
        data1.setNamespace(namespace);
        data1.setAttribute("key","d1");
        data1.setText(guid);
        node.addContent(data1);  
        
        graph.addContent(node);
    }
    /**
     * outputs the content of the document
     * @param doc xml document
	 * @author Berk PELENK <bpelenk@beengames.com>
	 * @version 1
     */
    public static void printAll(Document doc) {
        try{
            XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
            outputter.output(doc, System.out);
        } catch (java.io.IOException e){
            e.printStackTrace();
        }
    }    
}
